package com.ruoyi.business.service.impl;

import java.math.BigDecimal;
import java.util.List;
import java.util.Random;

import com.ruoyi.business.domain.Goods;
import com.ruoyi.business.domain.SalesDetailItem;
import com.ruoyi.business.mapper.GoodsMapper;
import com.ruoyi.business.service.ISalesDetailItemService;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.business.mapper.SalesMapper;
import com.ruoyi.business.domain.Sales;
import com.ruoyi.business.service.ISalesService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 销售Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-04-01
 */
@Service
public class SalesServiceImpl implements ISalesService 
{
    private static final Logger log = LoggerFactory.getLogger(SalesServiceImpl.class);
    
    @Autowired
    private SalesMapper salesMapper;
    
    @Autowired
    private ISalesDetailItemService salesDetailItemService;
    
    @Autowired
    private GoodsMapper goodsMapper;

    /**
     * 查询销售
     * 
     * @param id 销售主键
     * @return 销售
     */
    @Override
    public Sales selectSalesById(Long id)
    {
        return salesMapper.selectSalesById(id);
    }

    /**
     * 根据单据编号查询销售
     * 
     * @param receiptCode 单据编号
     * @return 销售
     */
    @Override
    public Sales selectSalesByReceiptCode(String receiptCode)
    {
        return salesMapper.selectSalesByReceiptCode(receiptCode);
    }

    /**
     * 查询销售列表
     * 
     * @param sales 销售
     * @return 销售
     */
    @DataScope(userAlias = "s")
    @Override
    public List<Sales> selectSalesList(Sales sales)
    {
        return salesMapper.selectSalesList(sales);
    }

    /**
     * 新增销售
     * 
     * @param sales 销售
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertSales(Sales sales)
    {


        // 插入数据
        if (sales.getType().equals("receiveOrder")){
            // 1. 生成销售单号（如果没有）
            if (StringUtils.isEmpty(sales.getReceiptCode())) {
                String dateStr = DateUtils.dateTimeNow("yyyyMMdd");
                String receiptCode = "SL" + dateStr + String.format("%04d", new Random().nextInt(10000));
                sales.setReceiptCode(receiptCode);
                log.info("生成销售单号: {}", receiptCode);
            }
            return salesMapper.insertSales(sales);
        }



        try {
            log.info("开始处理新增销售单请求，客户ID：{}", sales.getCustomerId());
            
            // 1. 生成销售单号（如果没有）
            if (StringUtils.isEmpty(sales.getReceiptCode())) {
                String dateStr = DateUtils.dateTimeNow("yyyyMMdd");
                String receiptCode = "SL" + dateStr + String.format("%04d", new Random().nextInt(10000));
                sales.setReceiptCode(receiptCode);
                log.info("生成销售单号: {}", receiptCode);
            }


            
            // 2. 设置业务日期（如果没有）
            if (sales.getBusinessDate() == null) {
                sales.setBusinessDate(DateUtils.getNowDate());
            }
            
            // 3. 设置默认收款状态（如果没有）
            if (StringUtils.isEmpty(sales.getPaymentStatus())) {
                sales.setPaymentStatus("pending"); // pending, completed, cancelled
            }
            
            // 4. 设置创建时间
            sales.setCreateTime(DateUtils.getNowDate());




            // 5. 保存销售单主表
            log.info("开始保存销售单主表: {}", sales.getReceiptCode());
            int rows = salesMapper.insertSales(sales);
            log.info("销售单主表保存完成, ID: {}", sales.getId());




            if (sales.getId() == null) {
                throw new RuntimeException("销售单主表保存失败，未获取到ID");
            }
            
            // 6. 获取明细列表并处理
            List<SalesDetailItem> itemList = sales.getSalesDetailItemList();
            
            if (itemList != null && !itemList.isEmpty()) {
                log.info("销售单明细项数量: {}", itemList.size());
                
                // 总金额计算
                BigDecimal totalAmount = BigDecimal.ZERO;
                int itemCount = 0;
                
                for (SalesDetailItem item : itemList) {
                    try {
                        // 检查必要字段
                        if (item.getGoodsId() == null) {
                            log.warn("第{}个明细缺少商品ID，跳过", itemCount + 1);
                            continue;
                        }
                        
                        // 设置销售单ID关联
                        item.setSalesId(sales.getId());
                        item.setId(null); // 确保ID为空，以便插入新记录
                        
                        // 设置创建信息
                        item.setCreateBy(sales.getCreateBy());
                        item.setCreateTime(DateUtils.getNowDate());
                        
                        // 补充商品信息
                        Goods goods = goodsMapper.selectGoodsById(item.getGoodsId());
                        if (goods != null) {
                            item.setGoodsCode(goods.getGoodsCode());
                            item.setGoodsSpec(goods.getGoodsSpec());
                            item.setGoodsName(goods.getGoodsSpec());
                            
                            // 如果单价为空，使用商品的零售价
                            if (item.getUnitPrice() == null) {
                                item.setUnitPrice(goods.getRetailPrice());
                            }
                        }
                        
                        // 计算金额
                        if (item.getQuantity() != null && item.getUnitPrice() != null) {
                            BigDecimal itemAmount = item.getQuantity().multiply(item.getUnitPrice());
                            item.setTotalPrice(itemAmount);
                            
                            // 计算折后金额
                            if (item.getDiscount() != null && item.getDiscount().compareTo(BigDecimal.ZERO) > 0) {
                                BigDecimal discountRate = BigDecimal.ONE.subtract(
                                        item.getDiscount().divide(new BigDecimal("100")));
                                BigDecimal finalPrice = itemAmount.multiply(discountRate);
                                item.setFinalPrice(finalPrice);
                                
                                // 累加折后金额到总金额
                                totalAmount = totalAmount.add(finalPrice);
                            } else {
                                item.setFinalPrice(itemAmount);
                                // 累加原始金额到总金额
                                totalAmount = totalAmount.add(itemAmount);
                            }
                        } else {
                            log.warn("第{}个明细缺少数量或单价信息，设置默认值", itemCount + 1);
                            // 如果为null则设置默认值，防止NPE
                            if (item.getQuantity() == null) {
                                item.setQuantity(BigDecimal.ONE);
                            }
                            if (item.getUnitPrice() == null) {
                                item.setUnitPrice(BigDecimal.ZERO);
                            }
                            item.setTotalPrice(item.getQuantity().multiply(item.getUnitPrice()));
                            item.setFinalPrice(item.getTotalPrice());
                        }
                        
                        // 保存明细项
                        salesDetailItemService.insertSalesDetailItem(item);
                        
                        // 更新商品库存
                        updateGoodsStock(item);
                        
                        itemCount++;
                    } catch (Exception e) {
                        log.error("处理明细项时发生错误", e);
                        throw new RuntimeException("处理明细项失败: " + e.getMessage());
                    }
                }
                
                log.info("成功处理{}个明细项", itemCount);
                
                // 7. 更新总金额
                if (totalAmount.compareTo(BigDecimal.ZERO) > 0 &&
                    (sales.getTotalAmount() == null || 
                     sales.getTotalAmount().compareTo(BigDecimal.ZERO) == 0)) {
                    sales.setTotalAmount(totalAmount);
                    
                    // 更新主表金额
                    log.info("更新销售单总金额: {}", totalAmount);
                    salesMapper.updateSales(sales);
                }
            } else {
                log.warn("销售单请求没有包含明细项");
            }
            
            log.info("销售单 [{}] 保存完成", sales.getReceiptCode());
            return rows;
        } catch (Exception e) {
            log.error("保存销售单失败", e);
            throw new RuntimeException("保存销售单失败: " + e.getMessage(), e);
        }
    }

    /**
     * 修改销售
     * 
     * @param sales 销售
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateSales(Sales sales)
    {

        // 插入数据
        if (sales.getType().equals("receiveOrder")){
            return salesMapper.updateSales(sales);
        }


        try {
            log.info("开始处理修改销售单请求，ID：{}, 单号: {}", sales.getId(), sales.getReceiptCode());
            
            // 1. 查询原有销售单信息
            Sales originalSales = salesMapper.selectSalesById(sales.getId());
            if (originalSales == null) {
                throw new RuntimeException("找不到要修改的销售单信息，ID: " + sales.getId());
            }
            
            // 2. 设置更新时间
            sales.setUpdateTime(DateUtils.getNowDate());
            
            // 3. 保存销售单主表
            log.info("更新销售单主表: {}", sales.getReceiptCode());
            int rows = salesMapper.updateSales(sales);
            
            // 4. 获取明细列表并处理
            List<SalesDetailItem> itemList = sales.getSalesDetailItemList();
            
            if (itemList != null && !itemList.isEmpty()) {
                log.info("销售单明细项数量: {}", itemList.size());
                
                // 5. 查询原有明细项
                SalesDetailItem query = new SalesDetailItem();
                query.setSalesId(sales.getId());
                List<SalesDetailItem> originalItems = salesDetailItemService.selectSalesDetailItemList(query);
                log.info("原销售单明细项数量: {}", originalItems.size());
                
                // 6. 回滚原有销售记录的库存
                if (!originalItems.isEmpty()) {
                    log.info("回滚原销售单的库存记录");
                    for (SalesDetailItem item : originalItems) {
                        rollbackGoodsStock(item);
                    }
                    
                    // 7. 删除原有明细项
                    log.info("删除原有明细项");
                    for (SalesDetailItem item : originalItems) {
                        salesDetailItemService.deleteSalesDetailItemById(item.getId());
                    }
                }
                
                // 8. 重新插入明细项并更新库存
                BigDecimal totalAmount = BigDecimal.ZERO;
                int itemCount = 0;
                
                for (SalesDetailItem item : itemList) {
                    try {
                        // 检查必要字段
                        if (item.getGoodsId() == null) {
                            log.warn("第{}个明细缺少商品ID，跳过", itemCount + 1);
                            continue;
                        }
                        
                        // 设置销售单ID关联
                        item.setSalesId(sales.getId());
                        item.setId(null); // 确保ID为空，以便插入新记录
                        
                        // 设置创建和更新信息
                        if (StringUtils.isEmpty(item.getCreateBy())) {
                            item.setCreateBy(sales.getUpdateBy());
                        }
                        if (item.getCreateTime() == null) {
                            item.setCreateTime(DateUtils.getNowDate());
                        }
                        item.setUpdateBy(sales.getUpdateBy());
                        item.setUpdateTime(DateUtils.getNowDate());
                        
                        // 补充商品信息
                        Goods goods = goodsMapper.selectGoodsById(item.getGoodsId());
                        if (goods != null) {
                            if (StringUtils.isEmpty(item.getGoodsCode())) {
                                item.setGoodsCode(goods.getGoodsCode());
                            }
                            if (StringUtils.isEmpty(item.getGoodsSpec())) {
                                item.setGoodsSpec(goods.getGoodsSpec());
                            }
                            if (StringUtils.isEmpty(item.getGoodsName())) {
                                item.setGoodsName(goods.getGoodsSpec());
                            }
                            
                            // 如果单价为空，使用商品的零售价
                            if (item.getUnitPrice() == null) {
                                item.setUnitPrice(goods.getRetailPrice());
                            }
                        }
                        
                        // 计算金额
                        if (item.getQuantity() != null && item.getUnitPrice() != null) {
                            BigDecimal itemAmount = item.getQuantity().multiply(item.getUnitPrice());
                            item.setTotalPrice(itemAmount);
                            
                            // 计算折后金额
                            if (item.getDiscount() != null && item.getDiscount().compareTo(BigDecimal.ZERO) > 0) {
                                BigDecimal discountRate = BigDecimal.ONE.subtract(
                                        item.getDiscount().divide(new BigDecimal("100")));
                                BigDecimal finalPrice = itemAmount.multiply(discountRate);
                                item.setFinalPrice(finalPrice);
                                
                                // 累加折后金额到总金额
                                totalAmount = totalAmount.add(finalPrice);
                            } else {
                                item.setFinalPrice(itemAmount);
                                // 累加原始金额到总金额
                                totalAmount = totalAmount.add(itemAmount);
                            }
                        } else {
                            log.warn("第{}个明细缺少数量或单价信息，设置默认值", itemCount + 1);
                            if (item.getQuantity() == null) {
                                item.setQuantity(BigDecimal.ONE);
                            }
                            if (item.getUnitPrice() == null) {
                                item.setUnitPrice(BigDecimal.ZERO);
                            }
                            item.setTotalPrice(item.getQuantity().multiply(item.getUnitPrice()));
                            item.setFinalPrice(item.getTotalPrice());
                        }
                        
                        // 保存明细项
                        salesDetailItemService.insertSalesDetailItem(item);
                        
                        // 更新商品库存
                        updateGoodsStock(item);
                        
                        itemCount++;
                    } catch (Exception e) {
                        log.error("处理明细项时发生错误", e);
                        throw new RuntimeException("处理明细项失败: " + e.getMessage());
                    }
                }
                
                log.info("成功处理{}个明细项", itemCount);
                
                // 9. 更新总金额
                if (totalAmount.compareTo(BigDecimal.ZERO) > 0 &&
                    (sales.getTotalAmount() == null || 
                     sales.getTotalAmount().compareTo(BigDecimal.ZERO) == 0)) {
                    sales.setTotalAmount(totalAmount);
                    
                    // 更新主表金额
                    log.info("更新销售单总金额: {}", totalAmount);
                    salesMapper.updateSales(sales);
                }
            } else {
                log.warn("销售单修改请求没有包含明细项");
            }
            
            log.info("销售单 [{}] 修改完成", sales.getReceiptCode());
            return rows;
        } catch (Exception e) {
            log.error("修改销售单失败", e);
            throw new RuntimeException("修改销售单失败: " + e.getMessage(), e);
        }
    }

    /**
     * 批量删除销售
     * 
     * @param ids 需要删除的销售主键
     * @return 结果
     */
    @Override
    public int deleteSalesByIds(Long[] ids)
    {
        return salesMapper.deleteSalesByIds(ids);
    }

    /**
     * 删除销售信息
     * 
     * @param id 销售主键
     * @return 结果
     */
    @Override
    public int deleteSalesById(Long id)
    {
        return salesMapper.deleteSalesById(id);
    }
    
    /**
     * 更新商品库存 - 销售出库
     * 
     * @param item 销售单明细
     */
    private void updateGoodsStock(SalesDetailItem item) {
        if (item == null || item.getGoodsId() == null || item.getQuantity() == null) {
            return;
        }
        
        try {
            // 1. 查询商品信息
            Goods goods = goodsMapper.selectGoodsById(item.getGoodsId());
            if (goods == null) {
                log.error("找不到商品信息，ID: {}", item.getGoodsId());
                return;
            }
            
            // 2. 计算新库存（销售是减少库存）
            BigDecimal currentStock = goods.getStockQuantity() != null ? 
                    goods.getStockQuantity() : BigDecimal.ZERO;
            BigDecimal newStock = currentStock.subtract(item.getQuantity());
            
            // 检查库存是否足够，如果不足则只记录警告，但仍然允许出库
            if (newStock.compareTo(BigDecimal.ZERO) < 0) {
                log.warn("商品 [{}] 库存不足，当前库存：{}，需要销售：{}，出库后库存将为负数: {}", 
                         goods.getGoodsSpec(), currentStock, item.getQuantity(), newStock);
                // 不再抛出异常，允许库存为负
            }
            
            goods.setStockQuantity(newStock);
            
            // 3. 更新商品信息
            goods.setUpdateTime(DateUtils.getNowDate());
            goodsMapper.updateGoods(goods);
            
            log.info("商品 [{}] 库存更新: {} -> {}", goods.getGoodsSpec(), currentStock, newStock);
            
            // 4. 记录库存变动日志
            insertStockLog(item, "销售出库", currentStock, newStock);
            
        } catch (Exception e) {
            log.error("更新库存失败", e);
            throw new RuntimeException("更新库存失败: " + e.getMessage());
        }
    }
    
    /**
     * 回滚商品库存 - 取消销售
     * 
     * @param item 销售单明细
     */
    private void rollbackGoodsStock(SalesDetailItem item) {
        if (item == null || item.getGoodsId() == null || item.getQuantity() == null) {
            return;
        }
        
        try {
            // 1. 查询商品信息
            Goods goods = goodsMapper.selectGoodsById(item.getGoodsId());
            if (goods == null) {
                log.error("找不到商品信息，ID: {}", item.getGoodsId());
                return;
            }
            
            // 2. 计算新库存（回滚销售是增加库存）
            BigDecimal currentStock = goods.getStockQuantity() != null ? 
                    goods.getStockQuantity() : BigDecimal.ZERO;
            BigDecimal newStock = currentStock.add(item.getQuantity());
            goods.setStockQuantity(newStock);
            
            // 3. 更新商品信息
            goods.setUpdateTime(DateUtils.getNowDate());
            goodsMapper.updateGoods(goods);
            
            log.info("商品 [{}] 库存更新: {} -> {}", goods.getGoodsSpec(), currentStock, newStock);
            
            // 4. 记录库存变动日志
            insertStockLog(item, "取消销售入库", currentStock, newStock);
            
        } catch (Exception e) {
            log.error("回滚库存失败", e);
            throw new RuntimeException("回滚库存失败: " + e.getMessage());
        }
    }
    
    /**
     * 记录库存变动日志
     * 
     * @param item 操作相关明细
     * @param operationType 操作类型（销售出库/取消销售入库等）
     * @param beforeQuantity 操作前数量
     * @param afterQuantity 操作后数量
     */
    private void insertStockLog(SalesDetailItem item, String operationType, 
                               BigDecimal beforeQuantity, BigDecimal afterQuantity) {
        try {
            // 构建库存日志对象
            // 如果系统中已有StockLog实体类，使用该类；否则这里只做日志记录
            
            // 记录库存变动的关键信息
            String logMessage = String.format(
                "库存变动日志 - 操作类型: %s, 单据编号: %s, 商品ID: %s, 商品名称: %s, " +
                "变动数量: %s, 变动前: %s, 变动后: %s, 操作人: %s, 操作时间: %s",
                operationType,
                item.getSalesId(),
                item.getGoodsId(),
                item.getGoodsName(),
                item.getQuantity(),
                beforeQuantity,
                afterQuantity,
                item.getUpdateBy(),
                DateUtils.getTime()
            );
            
            log.info(logMessage);
            
            // TODO: 如果需要将库存变动记录持久化到数据库，可以在此处实现
            // StockLog stockLog = new StockLog();
            // stockLog.setGoodsId(item.getGoodsId());
            // stockLog.setGoodsName(item.getGoodsName());
            // stockLog.setOperationType(operationType);
            // stockLog.setBeforeQuantity(beforeQuantity);
            // stockLog.setAfterQuantity(afterQuantity);
            // stockLog.setChangeQuantity(item.getQuantity());
            // stockLog.setDocumentCode(item.getReceiptCode());
            // stockLog.setDocumentType("销售单");
            // stockLog.setCreateBy(item.getUpdateBy());
            // stockLog.setCreateTime(DateUtils.getNowDate());
            // stockLogMapper.insertStockLog(stockLog);
            
        } catch (Exception e) {
            log.error("记录库存变动日志失败", e);
            // 这里只记录异常，不抛出，避免影响主流程
        }
    }
}
